package cn.org.atool.generator.javafile.template;

import cn.org.atool.generator.database.model.TableSetter;
import com.squareup.javapoet.*;

import javax.lang.model.element.Modifier;

import static com.squareup.javapoet.ClassName.get;

/**
 * <p>
 * TODO
 * </p>
 *
 * @author by lishupeng
 * @date 2022/3/31 22:25
 */
public class ControllerFile extends AbstractTemplateFile {
    private char UNDERLINE = '_';

    public ControllerFile(TableSetter table) {
        super(table);
        this.packageName = getPackage(table);
        this.klassName = getClass(table);
    }

    public static String getPackage(TableSetter table) {
        return table.gc().getBasePackage() + ".controller";
    }

    public static String getClass(TableSetter table) {
        return table.getEntityPrefix() + "Controller";
    }

    /**
     * 文件构造
     *
     * @param spec
     */
    @Override
    protected void build(TypeSpec.Builder spec) {
        //service属性名
        String serviceFieldName = getFirstLowerName(ServiceInterfaceFile.getClass(table));
        //类属性
        FieldSpec field = FieldSpec.builder(ServiceInterfaceFile.getClassName(table), serviceFieldName)
                .addAnnotation(get("org.springframework.beans.factory.annotation", "Autowired"))
                .build();

        //添加类注解
        spec.addAnnotation(get("org.springframework.web.bind.annotation", "RestController"))
                .addAnnotation(get("lombok.extern.slf4j", "Slf4j"))
                .addAnnotation(AnnotationSpec.builder(get("org.springframework.web.bind.annotation", "RequestMapping"))
                        .addMember("value", "\"" + getPathName(table.getEntityPrefix()) + "\"")
                        .build())
                .addField(field);

        ClassName ValidatedClz = get("org.springframework.validation.annotation", "Validated");
        ClassName requestBodyClz = get("org.springframework.web.bind.annotation", "RequestBody");
        ClassName resultVOClz = get("com.dminfo.hms.common.domain.vo", "ResultVO");
        ClassName pageDTOClz = get("com.dminfo.hms.common.domain.dto", "PageDTO");
        ClassName idDTOClz = get("com.dminfo.hms.common.domain.dto", "IdDTO");
        ClassName entityClz = get(table.gc().getBasePackage() + ".entity", table.getEntityPrefix() + "Entity");

        //方法-分页
        spec.addMethod(MethodSpec.methodBuilder("page")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(getPostMethodAnnotation("/page"))
                .returns(resultVOClz)
                .addParameter(ParameterSpec.builder(pageDTOClz, "dto").addAnnotation(requestBodyClz).addAnnotation(ValidatedClz).build())
                .addStatement(String.format("return ResultVO.page(%s.page(dto))", serviceFieldName))
                .addJavadoc("分页")
                .build());

        //方法-列表
        spec.addMethod(MethodSpec.methodBuilder("list")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(getPostMethodAnnotation("/list"))
                .returns(resultVOClz)
                .addParameter(ParameterSpec.builder(entityClz, "entity").addAnnotation(requestBodyClz).addAnnotation(ValidatedClz).build())
                .addStatement(String.format("return ResultVO.success(%s.list(entity))", serviceFieldName))
                .addJavadoc("列表")
                .build());

        //方法-查询
        spec.addMethod(MethodSpec.methodBuilder("get")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(getPostMethodAnnotation("/get"))
                .returns(resultVOClz)
                .addParameter(ParameterSpec.builder(idDTOClz, "dto").addAnnotation(requestBodyClz).addAnnotation(ValidatedClz).build())
                .addStatement(String.format("return ResultVO.success(%s.getById(dto.getId()))", serviceFieldName))
                .addJavadoc("查询")
                .build());

        //方法-保存
        spec.addMethod(MethodSpec.methodBuilder("save")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(getPostMethodAnnotation("/save"))
                .returns(resultVOClz)
                .addParameter(ParameterSpec.builder(entityClz, "entity").addAnnotation(requestBodyClz).addAnnotation(ValidatedClz).build())
                .addStatement(String.format("%s.save(entity)",serviceFieldName))
                .addStatement("return ResultVO.success()")
                .addJavadoc("保存")
                .build());

        //方法-更新
        spec.addMethod(MethodSpec.methodBuilder("update")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(getPostMethodAnnotation("/update"))
                .returns(resultVOClz)
                .addParameter(ParameterSpec.builder(entityClz, "entity").addAnnotation(requestBodyClz).addAnnotation(ValidatedClz).build())
                .addStatement(String.format("%s.update(entity)",serviceFieldName))
                .addStatement("return ResultVO.success()")
                .addJavadoc("更新")
                .build());

        //方法-删除
        spec.addMethod(MethodSpec.methodBuilder("delete")
                .addModifiers(Modifier.PUBLIC)
                .addAnnotation(getPostMethodAnnotation("/delete"))
                .returns(resultVOClz)
                .addParameter(ParameterSpec.builder(idDTOClz, "dto").addAnnotation(requestBodyClz).addAnnotation(ValidatedClz).build())
                .addStatement(String.format("%s.delete(dto.getId())",serviceFieldName))
                .addStatement("return ResultVO.success()")
                .addJavadoc("删除")
                .build());

        spec.addJavadoc("$T: 控制类\n", super.className());
    }

    /**
     * 返回控制类里的方法的 postmapping注解
     *
     * @param path
     * @return
     */
    private AnnotationSpec getPostMethodAnnotation(String path) {
        return AnnotationSpec.builder(get("org.springframework.web.bind.annotation", "PostMapping"))
                .addMember("value", "\"" + path + "\"")
                .build();
    }

    /**
     * 是否接口类
     *
     * @return ignore
     */
    @Override
    protected boolean isInterface() {
        return false;
    }

    //=============私有方法=======

    private String getPathName(String name) {
        try {
            String[] arr = getUnderlineName(name).split(String.valueOf(UNDERLINE));
            String str = "";
            for (String a : arr) {
                str += "/" + a;
            }
            return str;
        } catch (Exception e) {
            return "";
        }
    }

    private String getUnderlineName(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (Character.isUpperCase(c)) {
                sb.append(UNDERLINE);
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        return sb.toString().substring(1);
    }

    /**
     * 首字母小写
     *
     * @param param
     * @return
     */
    private String getFirstLowerName(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        int len = param.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = param.charAt(i);
            if (i == 0) {
                sb.append(Character.toLowerCase(c));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }
}
